<template>
  <div class="app-container">
    <el-card shadow="never" class="detail-card">
      <div slot="header" class="card-header">
        <span class="page-title">会议详情</span>
        <el-button type="primary" size="small" @click="goBack">返回</el-button>
      </div>

      <div v-loading="loading" class="detail-content meeting-detail-content">
        <!-- <div class="meeting-detail-title">会议详情</div> -->

        <div class="meeting-section-title">基本信息</div>
        <div class="meeting-row-flex">
          <div class="meeting-col-flex">
            <table class="meeting-detail-table">
              <tr>
                <th>会议名称</th>
                <td class="value">{{ meetingData.meetingName || '未设置' }}</td>
              </tr>
              <tr>
                <th>发起人</th>
                <td class="value">{{ meetingData.creatorName || '未设置' }}</td>
              </tr>
              <tr>
                <th>会议室</th>
                <td class="value">{{ meetingData.meetingRoom || '未设置' }}</td>
              </tr>
            </table>
          </div>
          <div class="meeting-col-flex">
            <table class="meeting-detail-table">
              <tr>
                <th>会议时间</th>
                <td class="value">
                  {{ meetingData.meetingDate || '未设置' }}
                  {{ meetingData.startTime || '--' }} - {{ meetingData.endTime || '--' }}
                </td>
              </tr>
              <tr>
                <th>会议形式</th>
                <td class="value">
                  <dict-tag :options="dict.type.meeting_format" :value="meetingData.meetingType" size="small" />
                </td>
              </tr>
              <tr>
                <th>会议链接</th>
                <td class="value">
                  <template v-if="meetingData.tencentMeetingLink">
                    <a :href="meetingData.tencentMeetingLink" target="_blank" class="meeting-link">
                      {{ meetingData.tencentMeetingLink }}
                    </a>
                  </template>
                  <template v-else>未设置</template>
                </td>
              </tr>
            </table>
          </div>
        </div>

        <div class="meeting-section-title">参会信息</div>
        <table class="meeting-detail-table">
          <tr>
            <th>参会人员</th>
            <td class="value">
              <div v-if="meetingData.officeMeetingAttendeeList && Array.isArray(meetingData.officeMeetingAttendeeList)"
                class="attendee-tags">
                <el-tag v-for="(attendee, index) in meetingData.officeMeetingAttendeeList" :key="index" size="small">
                  {{ attendee.userName || attendee.nickName || attendee.userId }}
                </el-tag>
              </div>
              <span v-else>未设置</span>
            </td>
          </tr>
        </table>

        <div class="meeting-section-title">会议议程</div>
        <table class="meeting-detail-table">
          <tr>
            <th>议程</th>
            <td class="value">
              {{ meetingData.agenda || '未设置' }}
            </td>
          </tr>
        </table>
      </div>
    </el-card>

    <!-- 会议事项列表 -->
    <el-card shadow="never" class="task-card" style="margin-top: 20px;">
      <div class="task-card-header">
        <div class="page-title">会议事项</div>
        <div class="task-header-actions">
          <el-button type="primary" size="mini" @click="openEditTaskDialog" :disabled="taskLoading">编辑</el-button>
        </div>
      </div>
      <div v-loading="taskLoading" class="task-content">
        <el-table :data="taskList" border size="small" style="width: 100%">
          <el-table-column label="具体事项" prop="taskDescription" min-width="120" show-overflow-tooltip />
          <el-table-column label="责任人" prop="responsibleUserName" width="120" align="center" />
          <!-- <el-table-column label="责任人ID" prop="responsibleUserId" width="120" align="center" /> -->
          <el-table-column label="计划完成时间" prop="dueDate" width="180" align="center">
            <template slot-scope="scope">
              <span>{{ scope.row.dueDate }}</span>
            </template>
          </el-table-column>
          <el-table-column label="检查人" prop="checkerUserName" width="120" align="center" />
          <!-- <el-table-column label="检查人ID" prop="checkerUserId" width="120" align="center" /> -->
          <el-table-column label="进度说明" prop="progressExplanation" align="center" />
          <el-table-column label="是否完成" prop="isCompleted" width="100" align="center">
            <template slot-scope="scope">
              <el-tag :type="scope.row.isCompleted == 1 ? 'success' : 'info'" size="small">
                {{ scope.row.isCompleted == 1 ? '已完成' : '未完成' }}
              </el-tag>
            </template>
          </el-table-column>
          <!-- <el-table-column label="实际完成时间" prop="completionTime" width="180" align="center">
            <template slot-scope="scope">
              <span>{{ scope.row.completionTime }}</span>
            </template>
          </el-table-column> -->
        </el-table>
        <div v-if="!taskLoading && (!taskList || taskList.length === 0)" class="empty-tip">
          暂无任务数据
        </div>
      </div>
    </el-card>

    <!-- 会议附件 -->
    <el-card shadow="never" class="file-card" style="margin-top: 20px;">
      <div class="task-card-header">
        <div class="page-title">会议附件</div>
        <div class="task-header-actions">
          <el-button type="primary" size="mini" @click="openUploadDialog" :disabled="fileLoading">上传文件</el-button>
        </div>
      </div>
      <div v-loading="fileLoading" class="task-content">
        <div v-if="fileList && fileList.length" class="file-grid">
          <div class="file-card-item" v-for="file in fileList" :key="file.id">
            <div class="file-thumb">
              <span v-if="getFileIconType(file.fileName) === 'image'" class="file-icon-svg">
                <svg viewBox="0 0 64 64">
                  <rect x="8" y="8" width="48" height="48" rx="8" fill="#e0f7fa" />
                  <rect x="16" y="16" width="32" height="32" rx="4" fill="#00bcd4" />
                  <circle cx="26" cy="24" r="4" fill="#fff" />
                  <path d="M 18 36 L 26 28 L 32 34 L 38 28 L 38 40 L 18 40 Z" fill="#fff" />
                </svg>
              </span>
              <span v-else-if="getFileIconType(file.fileName) === 'word'" class="file-icon-svg">
                <svg viewBox="0 0 64 64">
                  <rect x="8" y="8" width="48" height="48" rx="8" fill="#e3eafd" />
                  <rect x="16" y="16" width="32" height="32" rx="4" fill="#1976d2" />
                  <text x="32" y="44" text-anchor="middle" font-size="22" fill="#fff" font-family="Arial">W</text>
                </svg>
              </span>
              <span v-else-if="getFileIconType(file.fileName) === 'excel'" class="file-icon-svg">
                <svg viewBox="0 0 64 64">
                  <rect x="8" y="8" width="48" height="48" rx="8" fill="#e8f5e9" />
                  <rect x="16" y="16" width="32" height="32" rx="4" fill="#43a047" />
                  <text x="32" y="44" text-anchor="middle" font-size="22" fill="#fff" font-family="Arial">X</text>
                </svg>
              </span>
              <span v-else-if="getFileIconType(file.fileName) === 'ppt'" class="file-icon-svg">
                <svg viewBox="0 0 64 64">
                  <rect x="8" y="8" width="48" height="48" rx="8" fill="#ffe5d0" />
                  <rect x="16" y="16" width="32" height="32" rx="4" fill="#ff9800" />
                  <text x="32" y="44" text-anchor="middle" font-size="22" fill="#fff" font-family="Arial">P</text>
                </svg>
              </span>
              <span v-else-if="getFileIconType(file.fileName) === 'pdf'" class="file-icon-svg">
                <svg viewBox="0 0 64 64">
                  <rect x="8" y="8" width="48" height="48" rx="8" fill="#ffeaea" />
                  <rect x="16" y="16" width="32" height="32" rx="4" fill="#e53935" />
                  <text x="32" y="44" text-anchor="middle" font-size="18" fill="#fff" font-family="Arial">PDF</text>
                </svg>
              </span>
              <span v-else-if="getFileIconType(file.fileName) === 'zip'" class="file-icon-svg">
                <svg viewBox="0 0 64 64">
                  <rect x="8" y="8" width="48" height="48" rx="8" fill="#fffde7" />
                  <rect x="16" y="16" width="32" height="32" rx="4" fill="#fbc02d" />
                  <text x="32" y="44" text-anchor="middle" font-size="18" fill="#fff" font-family="Arial">ZIP</text>
                </svg>
              </span>
              <span v-else-if="getFileIconType(file.fileName) === 'video'" class="file-icon-svg">
                <svg viewBox="0 0 64 64">
                  <rect x="8" y="8" width="48" height="48" rx="8" fill="#e1f5fe" />
                  <rect x="16" y="16" width="32" height="32" rx="4" fill="#039be5" />
                  <polygon points="26,24 40,32 26,40" fill="#fff" />
                </svg>
              </span>
              <span v-else-if="getFileIconType(file.fileName) === 'txt'" class="file-icon-svg">
                <svg viewBox="0 0 64 64">
                  <rect x="8" y="8" width="48" height="48" rx="8" fill="#f5f5f5" />
                  <rect x="16" y="16" width="32" height="32" rx="4" fill="#888" />
                  <text x="32" y="44" text-anchor="middle" font-size="18" fill="#fff" font-family="Arial">TXT</text>
                </svg>
              </span>
              <span v-else class="file-icon-svg">
                <svg viewBox="0 0 64 64">
                  <rect x="8" y="8" width="48" height="48" rx="8" fill="#f5f5f5" />
                  <rect x="16" y="16" width="32" height="32" rx="4" fill="#909399" />
                  <text x="32" y="44" text-anchor="middle" font-size="18" fill="#fff" font-family="Arial">FILE</text>
                </svg>
              </span>
            </div>
            <div class="file-info">
              <span class="file-name" :title="file.fileName">{{ file.fileName }}</span>
              <span class="file-meta">{{ formatFileSize(file.fileSize) }} · {{ parseTime(file.createTime) }}</span>
            </div>
            <div class="file-actions">
              <el-link type="primary" @click="handlePreview(file)">预览</el-link>
              <el-link type="danger" @click="handleFileDelete(file)" style="margin-left: 8px;">删除</el-link>
            </div>
          </div>
        </div>
        <div v-else class="empty-tip">
          暂无会议附件
        </div>

        <!-- 已读/未读列表 -->
        <div v-if="meetingData && meetingData.officeMeetingAttendeeList && meetingData.officeMeetingAttendeeList.length"
          class="attendee-status-list">
          <!-- 已读列表 -->
          <div v-if="readAttendees.length > 0" class="attendee-status-row">
            <div class="status-label">
              <span class="status-dot status-dot-read"></span>
              <span class="status-text">已读：</span>
            </div>
            <div class="attendee-list">
              <div v-for="attendee in readAttendees" :key="attendee.id || attendee.userId" class="attendee-item">
                <i class="el-icon-user attendee-icon"></i>
                <span class="attendee-name">{{ attendee.userName || attendee.name || '未知' }}</span>
              </div>
            </div>
          </div>

          <!-- 未读列表 -->
          <div v-if="unreadAttendees.length > 0" class="attendee-status-row">
            <div class="status-label">
              <span class="status-dot status-dot-unread"></span>
              <span class="status-text">未读：</span>
            </div>
            <div class="attendee-list">
              <div v-for="attendee in unreadAttendees" :key="attendee.id || attendee.userId" class="attendee-item">
                <i class="el-icon-user attendee-icon"></i>
                <span class="attendee-name">{{ attendee.userName || attendee.name || '未知' }}</span>
              </div>
            </div>
          </div>
        </div>
      </div>
    </el-card>

    <!-- 上传会议附件 -->
    <el-dialog title="上传会议附件" :visible.sync="uploadDialogVisible" width="420px" append-to-body>
      <el-upload action="" :auto-upload="false" :file-list="uploadFileList" :on-change="handleUploadChange"
        :on-remove="handleUploadRemove" multiple drag>
        <i class="el-icon-upload"></i>
        <div class="el-upload__text">将文件拖到此处，或<em>点击上传</em></div>
        <div class="el-upload__tip">支持同时上传多个文件</div>
      </el-upload>
      <span slot="footer" class="dialog-footer">
        <el-button @click="closeUploadDialog" :disabled="uploading">取 消</el-button>
        <el-button type="primary" @click="submitUploadFiles" :loading="uploading">上 传</el-button>
      </span>
    </el-dialog>

    <!-- 编辑会议事项 -->
    <el-dialog title="编辑会议事项" :visible.sync="editDialogVisible" width="1200px" append-to-body>
      <div class="edit-toolbar">
        <el-button type="primary" icon="el-icon-plus" size="mini" @click="addTaskRow">新增事项</el-button>
      </div>
      <el-table :data="editTaskList" border size="small" style="width: 100%" v-loading="taskDialogLoading">
        <el-table-column min-width="160">
          <template slot="header">
            <span style="color: #f56c6c;">*</span>
            <span>具体事项</span>
          </template>
          <template slot-scope="{ row }">
            <el-input v-model="row.taskDescription" size="mini" placeholder="请输入事项描述"
              :disabled="row.isCompleted == 1" />
          </template>
        </el-table-column>
        <el-table-column width="140">
          <template slot="header">
            <span style="color: #f56c6c;">*</span>
            <span>责任人</span>
          </template>
          <template slot-scope="{ row }">
            <el-select v-model="row.responsibleUserId" size="mini" placeholder="请选择责任人" clearable style="width: 100%;"
              :disabled="row.isCompleted == 1">
              <el-option v-for="attendee in meetingData.officeMeetingAttendeeList || []"
                :key="attendee.userId || attendee.id" :label="attendee.userName || attendee.name || '未知'"
                :value="attendee.userId || attendee.id">
              </el-option>
            </el-select>
          </template>
        </el-table-column>
        <el-table-column width="200">
          <template slot="header">
            <span style="color: #f56c6c;">*</span>
            <span>计划完成时间</span>
          </template>
          <template slot-scope="{ row }">
            <el-date-picker v-model="row.dueDate" type="date" size="mini" value-format="yyyy-MM-dd" placeholder="选择时间"
              style="width: 100%;" :disabled="row.isCompleted == 1" />
          </template>
        </el-table-column>
        <el-table-column label="检查人" width="140">
          <template slot-scope="{ row }">
            <el-select v-model="row.checkerUserId" size="mini" placeholder="请选择检查人" clearable style="width: 100%;"
              :disabled="row.isCompleted == 1">
              <el-option v-for="attendee in meetingData.officeMeetingAttendeeList || []"
                :key="attendee.userId || attendee.id" :label="attendee.userName || attendee.name || '未知'"
                :value="attendee.userId || attendee.id">
              </el-option>
            </el-select>
          </template>
        </el-table-column>
        <el-table-column label="进度说明" width="200">
          <template slot-scope="{ row }">
            <el-input v-model="row.progressExplanation" size="mini" placeholder="请输入进度说明"
              :disabled="row.isCompleted == 1" />
          </template>
        </el-table-column>
        <el-table-column label="是否完成" width="110" align="center">
          <template slot-scope="{ row }">
            <el-tag :type="row.isCompleted == 1 ? 'success' : 'info'" size="small">
              {{ row.isCompleted == 1 ? '已完成' : '未完成' }}
            </el-tag>
          </template>
        </el-table-column>
        <!-- <el-table-column label="实际完成时间" width="200">
          <template slot-scope="{ row }">
            <el-date-picker v-model="row.completionTime" type="datetime" size="mini" value-format="yyyy-MM-dd HH:mm:ss"
              placeholder="选择时间" style="width: 100%;" :disabled="row.isCompleted !== 1" />
          </template>
        </el-table-column> -->
        <el-table-column label="操作" width="80" align="center">
          <template slot-scope="{ $index }">
            <el-button type="text" size="mini" @click="removeTaskRow($index)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>
      <div slot="footer" class="dialog-footer">
        <el-button @click="editDialogVisible = false">取 消</el-button>
        <el-button type="primary" :loading="taskDialogLoading" @click="submitTaskChanges">保 存</el-button>
      </div>
    </el-dialog>

    <!-- 文件预览弹框 -->
    <el-dialog :visible.sync="previewDialogVisible" width="60vw" top="5vh" :title="getPreviewTitle()"
      @close="previewFile = null">
      <div v-if="previewFile">
        <!-- 图片预览 - 使用Element UI的图片预览功能 -->
        <el-image v-if="getFileIconType(previewFile.fileName) === 'image'" :src="previewFile.downloadUrl"
          :preview-src-list="previewFile.imageUrls || [previewFile.downloadUrl]" fit="contain"
          style="max-width:100%;max-height:70vh;display:block;margin:auto;cursor:pointer;"
          :initial-index="previewFile.currentImageIndex || 0">
          <div slot="error" class="image-slot">
            <i class="el-icon-picture-outline"></i>
          </div>
        </el-image>
        <!-- 视频预览 -->
        <video v-else-if="getFileIconType(previewFile.fileName) === 'video'" :src="previewFile.downloadUrl"
          style="max-width:100%;max-height:70vh;display:block;margin:auto;" controls></video>
        <!-- 文档/PDF/PPT/Word/Excel 预览：直接用iframe打开 -->
        <iframe v-else-if="['pdf', 'word', 'excel', 'ppt'].includes(getFileIconType(previewFile.fileName))"
          :src="previewFile.downloadUrl" style="width:100%;height:70vh;border:none;"></iframe>
        <!-- 其他类型提示 -->
        <div v-else style="text-align:center;padding:40px 0;color:#888;">
          暂不支持该类型文件的在线预览，请下载后查看。
        </div>
      </div>
    </el-dialog>

    <!-- 隐藏的图片预览组件，用于直接触发预览 -->
    <el-image v-if="previewFile && getFileIconType(previewFile.fileName) === 'image'" ref="hiddenImagePreview"
      :key="`preview-${previewFile.id}`" :src="previewFile.downloadUrl"
      :preview-src-list="previewFile.imageUrls || [previewFile.downloadUrl]" :initial-index="0" style="display: none;">
    </el-image>
  </div>
</template>

<script>
import { getMeetingRecord } from "@/api/officeMeeting/meetingRecord";
import { listMeetingTask, addMeetingTaskList, addMeetingFileInfo, getMeetingTaskFileList, delMeetingFile } from "@/api/officeMeeting/meetingTask";
import { fileLinkTransfer, fileLinkLooking } from "@/api/production/projectFileInfo";

export default {
  name: 'MeetingRecordDetail',
  dicts: ['meeting_format', 'meeting_matter_status'],
  data() {
    return {
      loading: false,
      meetingData: {},
      meetingId: null,
      taskLoading: false,
      taskList: [],
      editDialogVisible: false,
      editTaskList: [],
      taskDialogLoading: false,
      fileLoading: false,
      fileList: [],
      uploadDialogVisible: false,
      uploadFileList: [],
      uploading: false,
      previewDialogVisible: false,
      previewFile: null
    }
  },
  computed: {
    /** 已读人员列表 */
    readAttendees() {
      if (!this.meetingData || !this.meetingData.officeMeetingAttendeeList) {
        return []
      }
      return this.meetingData.officeMeetingAttendeeList.filter(item => item.isRead === 1)
    },
    /** 未读人员列表 */
    unreadAttendees() {
      if (!this.meetingData || !this.meetingData.officeMeetingAttendeeList) {
        return []
      }
      return this.meetingData.officeMeetingAttendeeList.filter(item => item.isRead === 0 || item.isRead === null || item.isRead === undefined)
    }
  },
  created() {
    // 从路由参数中获取 id
    this.meetingId = this.$route.params.id
    if (this.meetingId) {
      this.getDetail()
    } else {
      this.$modal.msgError('会议ID不存在')
      this.goBack()
    }
  },
  methods: {
    /** 获取会议详情 */
    getDetail() {
      this.loading = true
      getMeetingRecord(this.meetingId).then(response => {
        this.meetingData = response.data
        this.loading = false
        // 获取会议详情后，获取任务列表和附件列表
        this.getTaskList()
        this.getMeetingFiles()
      }).catch(() => {
        this.loading = false
        this.$modal.msgError('获取会议详情失败')
      })
    },
    /** 获取会议任务列表 */
    getTaskList() {
      if (!this.meetingId) {
        return
      }
      this.taskLoading = true
      listMeetingTask({
        meetingId: this.meetingId,
        pageNum: 1,
        pageSize: 1000  // 获取所有任务，不分页
      }).then(response => {
        this.taskList = response.rows || []
        this.taskLoading = false
      }).catch(() => {
        this.taskLoading = false
        this.$modal.msgError('获取任务列表失败')
      })
    },
    /** 获取会议附件列表 */
    getMeetingFiles() {
      if (!this.meetingId) {
        return
      }
      this.fileLoading = true
      getMeetingTaskFileList({ relatedRefId: this.meetingId }).then(response => {
        const { rows, data } = response || {}
        this.fileList = rows || data || []
        this.fileLoading = false
      }).catch(() => {
        this.fileLoading = false
        this.fileList = []
        this.$modal.msgError('获取会议附件失败')
      })
    },
    /** 打开编辑事项弹框 */
    openEditTaskDialog() {
      const list = Array.isArray(this.taskList) && this.taskList.length
        ? this.taskList.map(item => ({
          ...item,
          dueDate: item.dueDate ? item.dueDate : '',
          completionTime: item.completionTime ? item.completionTime : ''
        }))
        : [this.createEmptyTask()]
      this.editTaskList = list
      this.editDialogVisible = true
    },
    /** 创建一个默认的会议事项 */
    createEmptyTask() {
      return {
        id: null,
        meetingId: this.meetingId,
        projectId: this.meetingData ? this.meetingData.projectId : null,
        taskDescription: '',
        responsibleUserId: null,
        responsibleUserName: '',
        dueDate: '',
        checkerUserId: null,
        checkerUserName: '',
        isCompleted: 0,
        completionTime: null
      }
    },
    /** 新增一条会议事项 */
    addTaskRow() {
      this.editTaskList.push(this.createEmptyTask())
    },
    /** 删除会议事项 */
    removeTaskRow(index) {
      this.editTaskList.splice(index, 1)
    },
    /** 编辑表格状态变化 */
    handleEditRowStatusChange(row) {
      if (row.isCompleted === 1 && !row.completionTime) {
        row.completionTime = row.dueDate || new Date().toISOString().slice(0, 19).replace('T', ' ')
      }
      if (row.isCompleted !== 1) {
        row.completionTime = null
      }
    },
    /** 格式化时间字符串（处理包含T的情况） */
    parseDateTime(val) {
      if (!val) return ''
      if (typeof val === 'string' && val.length === 19 && val.indexOf('T') === -1) {
        return val
      }
      return this.parseTime(val, '{y}-{m}-{d} {h}:{i}:{s}')
    },
    /** 提交会议事项修改 */
    submitTaskChanges() {
      // if (!this.editTaskList.length) {
      //   this.$modal.msgError('请至少保留一条会议事项')
      //   return
      // }
      // 校验必填字段：具体事项、责任人、计划完成时间
      for (let i = 0; i < this.editTaskList.length; i++) {
        const item = this.editTaskList[i]
        if (!item.taskDescription || !item.taskDescription.trim()) {
          this.$modal.msgError(`第${i + 1}条会议事项的"具体事项"不能为空`)
          return
        }
        if (!item.responsibleUserId) {
          this.$modal.msgError(`第${i + 1}条会议事项的"责任人"不能为空`)
          return
        }
        if (!item.dueDate) {
          this.$modal.msgError(`第${i + 1}条会议事项的"计划完成时间"不能为空`)
          return
        }
      }
      // 获取参会人员列表，用于查找用户名称
      const attendeeList = this.meetingData && this.meetingData.officeMeetingAttendeeList ? this.meetingData.officeMeetingAttendeeList : []

      const payload = this.editTaskList.map(item => {
        const isCompleted = item.isCompleted === 1 ? 1 : 0

        // 根据 responsibleUserId 查找责任人名称
        let responsibleUserName = item.responsibleUserName || ''
        if (item.responsibleUserId) {
          const responsibleUser = attendeeList.find(attendee =>
            (attendee.userId === item.responsibleUserId) || (attendee.id === item.responsibleUserId)
          )
          if (responsibleUser) {
            responsibleUserName = responsibleUser.userName || responsibleUser.name || ''
          }
        }

        // 根据 checkerUserId 查找检查人名称
        let checkerUserName = item.checkerUserName || ''
        if (item.checkerUserId) {
          const checkerUser = attendeeList.find(attendee =>
            (attendee.userId === item.checkerUserId) || (attendee.id === item.checkerUserId)
          )
          if (checkerUser) {
            checkerUserName = checkerUser.userName || checkerUser.name || ''
          }
        }

        return {
          ...item,
          meetingName: this.meetingData.meetingName,
          meetingId: this.meetingId,
          projectId: item.projectId || (this.meetingData ? this.meetingData.projectId : null),
          isCompleted,
          dueDate: item.dueDate || null,
          completionTime: isCompleted === 1 ? (item.completionTime || item.dueDate || null) : null,
          responsibleUserId: item.responsibleUserId || null,
          responsibleUserName: responsibleUserName,
          checkerUserId: item.checkerUserId || null,
          checkerUserName: checkerUserName
        }
      })
      this.taskDialogLoading = true
      // console.log('payload', payload)
      addMeetingTaskList(this.meetingId, payload).then(() => {
        this.$modal.msgSuccess('保存成功')
        this.editDialogVisible = false
        this.getTaskList()
      }).catch(() => {
        this.$modal.msgError('保存失败')
      }).finally(() => {
        this.taskDialogLoading = false
      })
    },
    /** 返回上一页 */
    goBack() {
      this.$router.go(-1)
    },
    /** 获取会议状态文本 */
    getMeetingStatusText(status) {
      const statusMap = {
        1: '未开始',
        2: '进行中',
        3: '已完成'
      }
      return statusMap[status] || '未知'
    },
    /** 获取会议状态标签类型 */
    getMeetingStatusType(status) {
      const typeMap = {
        1: 'info',      // 未开始 - 灰色
        2: 'warning',   // 进行中 - 橙色
        3: 'success'    // 已完成 - 绿色
      }
      return typeMap[status] || ''
    },
    /** 获取会议状态图标 */
    getMeetingStatusIcon(status) {
      const iconMap = {
        1: 'el-icon-time',
        2: 'el-icon-video-play',
        3: 'el-icon-check'
      }
      return iconMap[status] || 'el-icon-question'
    },
    /** 打开上传附件弹窗 */
    openUploadDialog() {
      this.uploadFileList = []
      this.uploadDialogVisible = true
    },
    /** 关闭上传弹窗 */
    closeUploadDialog() {
      if (this.uploading) {
        return
      }
      this.uploadDialogVisible = false
      this.uploadFileList = []
    },
    /** 选择上传文件 */
    handleUploadChange(file, fileList) {
      this.uploadFileList = (fileList || []).map(item => item.raw || item)
    },
    /** 移除待上传文件 */
    handleUploadRemove(file, fileList) {
      this.uploadFileList = (fileList || []).map(item => item.raw || item)
    },
    /** 上传文件 */
    submitUploadFiles() {
      if (!this.meetingId) {
        this.$modal.msgError('会议ID缺失')
        return
      }
      if (!this.uploadFileList.length) {
        this.$modal.msgError('请先选择需要上传的文件')
        return
      }
      this.uploading = true
      addMeetingFileInfo(this.meetingId, this.uploadFileList).then(() => {
        this.$modal.msgSuccess('上传成功')
        this.uploadDialogVisible = false
        this.uploadFileList = []
        this.getMeetingFiles()
      }).catch(() => {
        this.$modal.msgError('上传失败')
      }).finally(() => {
        this.uploading = false
      })
    },
    /** 预览附件 */
    async handlePreview(file) {
      if (!file) {
        return
      }
      const downloadUrl = this.getFilePreviewUrl(file)
      if (!downloadUrl) {
        this.$modal.msgError('未获取到文件预览地址')
        return
      }
      try {
        let newUrl = ''
        const type = this.getFileIconType(file.fileName)

        // 图片和视频使用 fileLinkTransfer
        if (['image', 'video'].includes(type)) {
          const res = await fileLinkTransfer(downloadUrl)
          newUrl = res.data.url
        }
        // PDF、Word、Excel、PPT 使用 fileLinkLooking
        else if (['pdf', 'word', 'excel', 'ppt'].includes(type)) {
          const res = await fileLinkLooking(downloadUrl)
          newUrl = res.data.url
        }
        // 其他类型直接使用原链接
        else {
          newUrl = downloadUrl
        }

        if (!newUrl) {
          this.$modal.msgError('获取预览链接失败')
          return
        }

        // 如果是图片类型，直接触发Element UI的图片预览
        if (type === 'image') {
          this.previewFile = {
            ...file,
            downloadUrl: newUrl,
            imageUrls: [newUrl],
            currentImageIndex: 0
          }
          // 使用$nextTick确保DOM更新后触发预览
          this.$nextTick(() => {
            if (this.$refs.hiddenImagePreview) {
              this.$refs.hiddenImagePreview.clickHandler()
            }
          })
        } else {
          // 非图片类型使用弹框预览
          this.previewFile = { ...file, downloadUrl: newUrl }
          this.previewDialogVisible = true
        }
      } catch (e) {
        this.$modal.msgError('预览失败')
      }
    },
    /** 删除附件 */
    handleFileDelete(file) {
      if (!file) {
        this.$modal.msgError('文件信息不完整，无法删除')
        return
      }
      // 尝试多种可能的ID字段名
      const fileId = file.id
      if (!fileId) {
        this.$modal.msgError('文件ID不存在，无法删除')
        console.error('文件对象:', file)
        return
      }
      this.$modal.confirm(`确认删除文件"${file.fileName || ''}"吗？`).then(() => {

        return delMeetingFile(fileId)
      }).then((response) => {
        this.$modal.msgSuccess('删除成功')
        this.getMeetingFiles()
      }).catch((error) => {
        // 用户取消操作时不显示错误
        if (error !== 'cancel') {
          const errorMsg = error && error.message ? error.message : (error && error.msg ? error.msg : '未知错误')
          this.$modal.msgError('删除失败：' + errorMsg)
        }
      })
    },
    /** 格式化文件大小 */
    formatFileSize(size) {
      if (size === null || size === undefined) {
        return '-'
      }
      const num = Number(size)
      if (Number.isNaN(num)) {
        return size
      }
      if (num === 0) {
        return '0B'
      }
      const units = ['B', 'KB', 'MB', 'GB', 'TB']
      let index = 0
      let value = num
      while (value >= 1024 && index < units.length - 1) {
        value /= 1024
        index += 1
      }
      return `${value.toFixed(index === 0 ? 0 : 2)}${units[index]}`
    },
    /** 判断是否为图片文件 */
    isImageFile(file) {
      const name = (file && file.fileName) || ''
      const ext = name.split('.').pop().toLowerCase()
      return ['png', 'jpg', 'jpeg', 'gif', 'bmp', 'svg', 'webp'].includes(ext)
    },
    /** 获取文件预览地址 */
    getFilePreviewUrl(file) {
      if (!file) return ''
      return file.fileUrl || file.previewUrl || file.downloadUrl || file.url || ''
    },
    /** 根据文件类型获取图标类型 */
    getFileIconType(fileName) {
      if (!fileName) return 'file'
      const ext = fileName.split('.').pop().toLowerCase()
      if (['doc', 'docx'].includes(ext)) return 'word'
      if (['xls', 'xlsx', 'csv'].includes(ext)) return 'excel'
      if (['ppt', 'pptx'].includes(ext)) return 'ppt'
      if (ext === 'pdf') return 'pdf'
      if (['png', 'jpg', 'jpeg', 'gif', 'bmp', 'svg', 'webp'].includes(ext)) return 'image'
      if (['mp4', 'avi', 'mov', 'wmv', 'flv', 'mkv', 'webm', 'mpeg', 'mpg'].includes(ext)) return 'video'
      if (['txt', 'md'].includes(ext)) return 'txt'
      if (['zip', 'rar', '7z', 'tar', 'gz'].includes(ext)) return 'zip'
      return 'file'
    },
    /** 获取预览标题 */
    getPreviewTitle() {
      if (!this.previewFile) return '预览'
      const type = this.getFileIconType(this.previewFile.fileName)
      if (type === 'image' && this.previewFile.imageUrls && this.previewFile.imageUrls.length > 1) {
        const currentIndex = this.previewFile.currentImageIndex || 0
        const total = this.previewFile.imageUrls.length
        return `${this.previewFile.fileName} (${currentIndex + 1}/${total})`
      }
      return this.previewFile.fileName
    }
  }
}
</script>

<style lang="scss" scoped>
// SASS 变量定义
$color-primary: #303133;
$color-secondary: #909399;
$color-border: #ebeef5;
$color-border-hover: #dcdfe6;
$color-bg: #fff;
$color-bg-light: #f5f7fa;
$color-bg-lighter: #f9fafc;
$color-bg-green: #f0f9eb;

$font-size-title: 18px;
$font-size-normal: 14px;
$font-size-small: 12px;
$font-size-large: 30px;

$spacing-xs: 4px;
$spacing-sm: 8px;
$spacing-md: 12px;
$spacing-lg: 20px;
$spacing-xl: 40px;

$border-radius-sm: 4px;
$border-radius-md: 6px;
$border-radius-lg: 8px;

$z-index-viewer: 2100;

$transition-base: 0.2s;
$transition-slow: 0.3s;

// 主容器
.app-container {
  padding: $spacing-lg;
}

// 详情卡片
.detail-card {
  .card-header {
    display: flex;
    justify-content: space-between;
    align-items: center;

    .page-title {
      font-size: $font-size-title;
      font-weight: 600;
    }
  }

  .detail-content {
    // padding: $spacing-lg 0;

    .meeting-detail-title {
      font-size: 22px;
      font-weight: 600;
      color: #2d3a4b;
      margin-bottom: $spacing-md;
      letter-spacing: 1px;
    }

    .meeting-section-title {
      font-size: 18px;
      color: #4a90e2;
      font-weight: 600;
      margin: 12px 0 12px;
      border-left: 4px solid #4a90e2;
      padding-left: 12px;
    }

    .meeting-row-flex {
      display: flex;
      gap: 24px;
      flex-wrap: wrap;

      .meeting-col-flex {
        flex: 1;
        min-width: 280px;
      }
    }

    .meeting-detail-table {
      width: 100%;
      border-collapse: separate;
      border-spacing: 0;

      th,
      td {
        padding: 10px 8px;
        border-bottom: 1px solid #f0f0f0;
        font-size: 15px;
      }

      th {
        width: 120px;
        color: #6b7a90;
        text-align: center;
        font-weight: 500;
        vertical-align: top;
        padding-right: 12px;
        background: none;
      }

      td.value {
        color: #222;
        text-align: left;
        font-weight: 500;
      }

      tr:last-child th,
      tr:last-child td {
        border-bottom: none;
      }
    }

    .meeting-link {
      color: #409EFF;
      word-break: break-all;

      &:hover {
        text-decoration: underline;
      }
    }

    .attendee-tags {
      display: flex;
      flex-wrap: wrap;
      gap: 8px;

      ::v-deep .el-tag {
        margin: 0;
      }
    }
  }
}

// 任务卡片
.task-card {
  .task-card-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: $spacing-md;
    width: 100%;

    .page-title {
      font-size: $font-size-title;
      font-weight: 600;
    }

    .task-header-actions {
      margin-left: auto;
      display: flex;
      align-items: center;
    }
  }

  .task-content {
    padding: $spacing-lg 0;

    .empty-tip {
      text-align: center;
      padding: $spacing-xl 0;
      color: $color-secondary;
      font-size: $font-size-normal;
    }
  }
}

// 文件卡片
.file-card {
  .task-card-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: $spacing-md;
    width: 100%;

    .page-title {
      font-size: $font-size-title;
      font-weight: 600;
    }

    .task-header-actions {
      margin-left: auto;
      display: flex;
      align-items: center;
    }
  }

  .task-content {
    padding: $spacing-lg 0;

    .empty-tip {
      text-align: center;
      padding: $spacing-xl 0;
      color: $color-secondary;
      font-size: $font-size-normal;
    }
  }

  .file-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: 16px;
  }

  .file-card-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: $spacing-md;
    border: 1px solid $color-border;
    border-radius: $border-radius-lg;
    background: $color-bg;
    transition: box-shadow $transition-base;

    &:hover {
      box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
    }

    .file-thumb {
      width: 80px;
      height: 80px;
      border-radius: $border-radius-md;
      overflow: hidden;
      margin-bottom: $spacing-sm;
      background: $color-bg-light;
      display: flex;
      align-items: center;
      justify-content: center;

      .el-image {
        width: 100%;
        height: 100%;
      }

      .file-icon-svg {
        width: 100%;
        height: 100%;
        display: flex;
        align-items: center;
        justify-content: center;

        svg {
          width: 100%;
          height: 100%;
        }
      }
    }

    .file-info {
      width: 100%;
      text-align: center;

      .file-name {
        display: block;
        font-size: $font-size-normal;
        color: $color-primary;
        margin-bottom: $spacing-xs;
        word-break: break-all;
        overflow: hidden;
        text-overflow: ellipsis;
        display: -webkit-box;
        -webkit-line-clamp: 1;
        line-clamp: 1;
        -webkit-box-orient: vertical;
      }

      .file-meta {
        display: block;
        font-size: $font-size-small;
        color: $color-secondary;
      }
    }

    .file-actions {
      margin-top: $spacing-sm;
    }
  }
}

// 编辑工具栏
.edit-toolbar {
  display: flex;
  justify-content: flex-end;
  margin-bottom: $spacing-md;
}

// 已读/未读列表样式
.attendee-status-list {
  margin-top: $spacing-lg;
  padding-top: $spacing-lg;
  border-top: 1px solid $color-border;
}

.attendee-status-row {
  display: flex;
  align-items: flex-start;
  margin-bottom: $spacing-md;

  &:last-child {
    margin-bottom: 0;
  }

  .status-label {
    display: flex;
    align-items: center;
    min-width: 80px;
    margin-right: $spacing-md;

    .status-dot {
      display: inline-block;
      width: 8px;
      height: 8px;
      border-radius: 50%;
      margin-right: $spacing-xs;
    }

    .status-dot-read {
      background-color: #67c23a;
    }

    .status-dot-unread {
      background-color: $color-secondary;
    }

    .status-text {
      font-size: $font-size-normal;
      color: $color-primary;
      font-weight: 500;
    }
  }

  .attendee-list {
    display: flex;
    flex-wrap: wrap;
    gap: $spacing-md;
    flex: 1;

    .attendee-item {
      display: flex;
      align-items: center;
      gap: $spacing-xs;

      .attendee-icon {
        font-size: 16px;
        color: $color-secondary;
      }

      .attendee-name {
        font-size: $font-size-normal;
        color: $color-primary;
      }
    }
  }
}

// 图片预览样式
.image-slot {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 100%;
  color: $color-secondary;
  font-size: $font-size-large;
  background-color: $color-bg-light;
  border-radius: $border-radius-sm;
}

// 图片预览弹窗样式优化
::v-deep {
  .el-image-viewer__wrapper {
    z-index: $z-index-viewer;
  }

  .el-image-viewer__img {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
  }

  .el-image-viewer__btn {
    background-color: rgba(0, 0, 0, 0.5);
    color: #fff;
    border-radius: 50%;
    width: 44px;
    height: 44px;
    line-height: 44px;
    font-size: $font-size-title;

    &:hover {
      background-color: rgba(0, 0, 0, 0.7);
    }
  }

  .el-image-viewer__actions {
    background-color: rgba(0, 0, 0, 0.5);
    border-radius: $border-radius-sm;

    &__inner {
      color: #fff;

      i {
        color: #fff;
        font-size: 16px;
      }
    }
  }
}
</style>
